//*********************************************************************
//		Copyright (c) 2003 - 2008 Microsoft Corporation.
//      This code is provided under Microsoft Public License, which can be found at
//      http://www.microsoft.com/resources/sharedsource/licensingbasics/publiclicense.mspx 
//
// @File: Recorder.cs
//
// Purpose: records collected dta to a file
//
//
//
// Notes: 
//
//
//	
// History: 
//     @Version: V2.1
//
//     10/31/08 PGV 2.1.001.0 Starting V2.1 (based on 2.0.002.0 code)
//
//
// @EndHeader@
//*********************************************************************


using System;
using System.IO;
using System.Threading;
using System.Diagnostics;
using Microsoft.Win32;
using System.Text;

namespace PerfService
{
	public class Recorder 
	{
		string m_FileName;
		string m_fstamp, m_suffix;
		StreamWriter m_stream;
		bool m_StopFlag = false;
		Guid m_bGUID;
		int m_count = 0;
        StringBuilder m_sb;
		private RegistryKey m_rk;

        public string FileName { get { return m_FileName; } }

        public Recorder ()
        {
            m_sb = new StringBuilder ();
        }

		public void Init ()
		{
			m_rk = (Registry.LocalMachine).OpenSubKey ("SOFTWARE", true);
            m_rk = m_rk.OpenSubKey("Microsoft", true);
            m_rk = m_rk.OpenSubKey("SQLH2PerfCollector", true);

			OpenFile (false);
		}

		void CloseFile ()
		{
			m_stream.Flush ();
			m_stream.Close ();

			string Nname = Constants.OutputDir+"\\pfc"+m_fstamp+m_suffix+".txt";
			File.Move (m_FileName, Nname);
		}

		bool OpenFile (bool closePrevious)
		{
			int i=0;
			string name,
				bname;

			if (closePrevious) CloseFile ();

			m_fstamp = DateTime.Now.ToString ("MMddyyHHmmss");
			m_suffix = "";
			bname = Constants.OutputDir+"\\pf"+m_fstamp;
			name = bname+".txt";

			while (File.Exists (name) && i<Constants.FileNameResolutionAttempts) 
			{
				m_suffix = "_"+i.ToString ();
				name = bname+m_suffix+".txt";
				++i;
			}
			if (i == Constants.FileNameResolutionAttempts) return false;

			m_FileName = name;
			m_stream = new StreamWriter (new FileStream (m_FileName, FileMode.Create, FileAccess.Write));
			m_bGUID = Guid.NewGuid ();

			m_rk.SetValue ("CurrentFile", m_FileName);
			WriteHeader ();
			return true;
		}

		void WriteHeader ()
		{
			m_stream.WriteLine (SQLH2PerfCollector.InstallationGuid+","+SQLH2PerfCollector.RunGuid+","+m_bGUID+",,");
			Configurator.WriteArrays (m_stream);
		}

        void Write (ResultRecord rr)
        {
            m_sb.Length = 0;
            m_sb.Append (rr.ComputerId);
            m_sb.Append (",");
            m_sb.Append (rr.CounterId);
            m_sb.Append (",");
            m_sb.Append (rr.Value);
            m_sb.Append (",");
            m_sb.Append (rr.CollectionId);
            m_sb.Append (",");
            m_sb.Append (rr.Timestamp);

            m_stream.WriteLine (m_sb.ToString ());
        }

		public void Run ()
		{
			ResultRecord rr;

			for (;;)
			{
				try 
				{
					rr = (ResultRecord)PerfMgr.ResultQueue.Dequeue ();
					Write (rr);
					++m_count;
					if ((m_count % Constants.FileLengthCheckFrequency) == 0)
					{
						FileInfo fi = new FileInfo (m_FileName);
                        if (fi.Length > Constants.MaxFileSize)
                        {
                            // Wrap file
                            OpenFile (true);
                        }
					}
						
				}
				catch (InvalidOperationException)
				{
					if (m_StopFlag) 
					{
						// m_count records written. Recorder stops writing.
						break;
					}
					// m_count records written. Recorder goes to sleep.
					Thread.Sleep (1000 * Constants.RecorderSleepTimeSeconds);
					Debug.WriteLine (DateTime.Now+",Recorder: Queue count,"+PerfMgr.ResultQueue.Count+",,,,,,,");
				}
				catch (Exception ex)
				{
					SQLH2PerfCollector.Log (ex.Message, EventLogEntryType.Error, 60);
					SQLH2PerfCollector.Log (ex.StackTrace, EventLogEntryType.Error, 600);
					try
					{
						CloseFile ();
					} 
					catch {}
					SQLH2PerfCollector.EmergencyExit ();
				}
			}

			CloseFile ();
		}

        public void Stop ()
        {
            m_StopFlag = true;
        }
	}
}
